package com.chengshi.shop.service.order.impl;

import com.chengshi.shop.dao.goods.GoodsProductMapper;
import com.chengshi.shop.dao.member.MemberAccountLogMapper;
import com.chengshi.shop.dao.member.MemberMapper;
import com.chengshi.shop.dao.order.*;
import com.chengshi.shop.dao.system.ExpressMapper;
import com.chengshi.shop.dao.system.SequenceMapper;
import com.chengshi.shop.dao.system.ShopConfigMapper;
import com.chengshi.shop.model.member.Member;
import com.chengshi.shop.model.member.MemberAccountLog;
import com.chengshi.shop.model.order.Order;
import com.chengshi.shop.model.order.OrderHistory;
import com.chengshi.shop.model.order.OrderItem;
import com.chengshi.shop.model.order.OrderPayment;
import com.chengshi.shop.model.system.Sequence;
import com.chengshi.shop.service.order.OrderService;
import com.chengshi.shop.service.wechat.MessageService;
import com.chengshi.shop.util.DateFormatUtil;
import com.chengshi.shop.util.EnumUtil;
import com.chengshi.shop.util.SessionUtils;
import com.github.binarywang.wxpay.bean.request.WxPayBaseRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * 订单相关接口
 *
 * @author xuxinlong
 * @version 2017年07月24日
 */
@Service
public class OrderServiceImpl implements OrderService {
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private GoodsProductMapper goodsProductMapper;
    @Resource
    private OrderHistoryMapper orderHistoryMapper;
    @Resource
    private OrderItemMapper orderItemMapper;
    @Resource
    private OrderPaymentMapper orderPaymentMapper;
    @Resource
    private SequenceMapper sequenceMapper;
    @Resource
    private ExpressMapper expressMapper;
    @Resource
    private OrderGiftMapper orderGiftMapper;
    @Resource
    private MemberMapper memberMapper;
    @Resource
    private MemberAccountLogMapper memberAccountLogMapper;
    @Resource
    private ShopConfigMapper shopConfigMapper;
    @Resource
    private WxPayService wxPayService;
    @Resource
    private MessageService messageService;

    /**
     * 订单列表
     *
     * @param inMap
     * @return
     */
    @Override
    public List<Order> getOrderList(HashMap<String, Object> inMap) {
        return orderMapper.getOrderList(inMap);
    }

    /**
     * 获取订单详情
     *
     * @param orderId
     * @return
     */
    @Override
    public Order getOrderByOrderId(Integer orderId) {
        return orderMapper.selectByPrimaryKey(orderId);
    }


    /**
     * 关闭订单
     *
     * @param order
     * @param opName
     * @param comments
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void closeOrder(Order order, String opName, String comments) {
        // 返回积分
        List<OrderPayment> orderPaymentList = orderPaymentMapper.getListByOrderId(order.getOrderId(), EnumUtil.PAYMENT_METHOD.积分.getValue().byteValue());
        for (OrderPayment orderPayment : orderPaymentList) {
            BigDecimal points = orderPayment.getMoney().multiply(new BigDecimal(shopConfigMapper.getConfig("POINTS_RATIO")));
            memberMapper.addMemberPoints(order.getMemberId(), points);
            //插入返还记录
            MemberAccountLog memberAccountLog = new MemberAccountLog();
            memberAccountLog.setMemberId(order.getMemberId());
            memberAccountLog.setAccountType(EnumUtil.ACCOUNT_TYPE.会员积分.getValue().byteValue());
            memberAccountLog.setNumber(points);
            memberAccountLog.setCreateTime(new Date());
            memberAccountLog.setContent("订单：" + order.getOrderNum() + "关闭，退还积分");
            memberAccountLog.setFromType(EnumUtil.ACCOUNT_FROM_TYPE.订单退还.getValue().byteValue());
            memberAccountLogMapper.insertSelective(memberAccountLog);
        }
        // 返回余额
        List<OrderPayment> orderPaymentList1 = orderPaymentMapper.getListByOrderId(order.getOrderId(), EnumUtil.PAYMENT_METHOD.余额支付.getValue().byteValue());
        for (OrderPayment orderPayment : orderPaymentList1) {
            memberMapper.addMemberBalance(order.getMemberId(), orderPayment.getMoney());
            //插入返还记录
            MemberAccountLog memberAccountLog = new MemberAccountLog();
            memberAccountLog.setMemberId(order.getMemberId());
            memberAccountLog.setAccountType(EnumUtil.ACCOUNT_TYPE.会员余额.getValue().byteValue());
            memberAccountLog.setNumber(orderPayment.getMoney());
            memberAccountLog.setCreateTime(new Date());
            memberAccountLog.setContent("订单：" + order.getOrderNum() + "关闭，退还余额");
            memberAccountLog.setFromType(EnumUtil.ACCOUNT_FROM_TYPE.订单退还.getValue().byteValue());
            memberAccountLogMapper.insertSelective(memberAccountLog);
        }

        List<OrderPayment> orderPaymentList2 = orderPaymentMapper.getListByOrderId(order.getOrderId(), EnumUtil.PAYMENT_METHOD.微信支付.getValue().byteValue());
        for (OrderPayment orderPayment : orderPaymentList2) {
            try {
                WxPayRefundRequest request = new WxPayRefundRequest();
                request.setOutRefundNo(this.getOrderNum());
                request.setOutTradeNo(order.getOrderNum());
                request.setTotalFee(WxPayBaseRequest.yuanToFee(orderPayment.getMoney().toString()));
                request.setRefundFee(WxPayBaseRequest.yuanToFee(orderPayment.getMoney().toString()));
                WxPayRefundResult result = wxPayService.refund(request);
                if ("FAIL".equals(result.getReturnCode())) {
                    throw new RuntimeException("微信退款失败：" + result.getReturnMsg());
                } else if ("FAIL".equals(result.getResultCode())) {
                    throw new RuntimeException("微信退款失败：" + result.getErrCodeDes());
                }
            } catch (WxPayException e) {
                e.printStackTrace();
                throw new RuntimeException("微信退款失败" + e.getErrCodeDes());
            }
        }

        List<OrderItem> orderItemList = orderItemMapper.getListByOrderId(order.getOrderId());
        for (OrderItem orderItem : orderItemList) {
            orderItem.setStatus(EnumUtil.ORDER_ITEM_STATUS.取消发货.getValue().byteValue());
            orderItemMapper.updateByPrimaryKeySelective(orderItem);
            //返还库存
            goodsProductMapper.addProductStore(orderItem.getProductId(), orderItem.getProductNum());
        }
        // 关闭订单
        order.setStatus(EnumUtil.ORDER_STATUS.交易关闭.getValue().byteValue());
        orderMapper.updateByPrimaryKeySelective(order);
        this.saveOrderHistory(order, opName, comments);
        //给会员发送微信模板消息
        Member member = memberMapper.selectByPrimaryKey(order.getMemberId());
        messageService.orderCloseMsg(order, comments, member.getOpenId());
    }


    /**
     * 保存订单历史
     *
     * @param order
     * @param opName
     * @param content
     */
    @Override
    public void saveOrderHistory(Order order, String opName, String content) {
        OrderHistory orderHistory = new OrderHistory();
        orderHistory.setCreateTime(new Date());
        orderHistory.setOrderId(order.getOrderId());
        orderHistory.setOpName(opName);
        orderHistory.setContent(content);
        orderHistoryMapper.insertSelective(orderHistory);
    }

    /**
     * 根据订单编号查询订单
     *
     * @param orderNum
     * @return
     */
    @Override
    public Order getOrderByOrderNum(String orderNum) {
        return orderMapper.getOrderByOrderNum(orderNum);
    }

    /**
     * 更新订单信息
     *
     * @param order
     */
    @Override
    public void updateByPrimaryKeySelective(Order order) {
        orderMapper.updateByPrimaryKeySelective(order);
    }

    /**
     * 查询用户拥有的有效订单
     *
     * @param memberId
     * @return
     */
    @Override
    public List<Order> getValidListByMemberId(Integer memberId) {
        return orderMapper.getValidListByMemberId(memberId);
    }

    /**
     * 查询用户拥有的订单
     *
     * @param memberId
     * @param status
     * @return
     */
    @Override
    public List<Order> getListByMemberId(Integer memberId, Byte status) {
        return orderMapper.getListByMemberId(memberId, status);
    }

    /**
     * 确认收货
     *
     * @param orderId
     * @param opName
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveReceipt(Integer orderId, String opName) {
        Order order = orderMapper.selectByPrimaryKey(orderId);
        // 确认收货
        if (order.getStatus() != EnumUtil.ORDER_STATUS.待收货.getValue().byteValue()) {
            throw new RuntimeException("订单状态已改变，不能确认收货");
        }

        List<OrderItem> itemsList = orderItemMapper.getListByOrderId(orderId);
        // 子订单确认收货
        String deliveryGoods = "";
        for (OrderItem orderItem : itemsList) {
            orderItem.setStatus(EnumUtil.ORDER_ITEM_STATUS.确认收货.getValue().byteValue());
            orderItemMapper.updateByPrimaryKeySelective(orderItem);
            deliveryGoods = orderItem.getGoodsName();
        }

        if (itemsList.size() > 1) {
            deliveryGoods += "等" + itemsList.size() + "件商品";
        }

        this.saveOrderHistory(order, opName, opName + "已经确认收货");

        // 更新主订单状态
        order.setStatus(EnumUtil.ORDER_STATUS.交易成功.getValue().byteValue());
        order.setFinishTime(new Date());
        orderMapper.updateByPrimaryKeySelective(order);

        //订单赠送积分(取整数)
        BigDecimal memberPoints = order.getTotalAmount().setScale(0, BigDecimal.ROUND_DOWN);
        memberMapper.addMemberPoints(order.getMemberId(), memberPoints);
        //插入记录
        MemberAccountLog memberAccountLog = new MemberAccountLog();
        memberAccountLog.setMemberId(order.getMemberId());
        memberAccountLog.setAccountType(EnumUtil.ACCOUNT_TYPE.会员积分.getValue().byteValue());
        memberAccountLog.setNumber(memberPoints);
        memberAccountLog.setCreateTime(new Date());
        memberAccountLog.setContent("购买商品赠送积分");
        memberAccountLog.setFromType(EnumUtil.ACCOUNT_FROM_TYPE.系统赠送.getValue().byteValue());
        memberAccountLogMapper.insertSelective(memberAccountLog);
        //发送微信消息
        Member member = memberMapper.selectByPrimaryKey(order.getMemberId());
        messageService.orderReceiptMsg(order, deliveryGoods, member.getOpenId());
    }

    /**
     * 生成订单唯一编号
     *
     * @return
     */
    @Override
    public String getOrderNum() {
        Sequence sequence = new Sequence();
        sequenceMapper.insert(sequence);
        int len = 5;
        String orderNum = sequence.getId().toString();
        orderNum = addZeroForNum(orderNum, len);
        orderNum = DateFormatUtil.formatDate(new Date(), "yyyyMMdd") + orderNum;
        return orderNum;
    }

    /**
     * 查询过期未付款的订单
     *
     * @return
     */
    @Override
    public List<Order> getOverdueOrder() {
        return orderMapper.getOverdueOrder();
    }

    /**
     * 商家开始发货
     *
     * @param order
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrderDelivery(Order order) {
        //改变主订单状态
        order.setStatus(EnumUtil.ORDER_STATUS.待收货.getValue().byteValue());
        order.setDeliveryTime(new Date());
        order.setAutoFinishTime(new Date(System.currentTimeMillis() + Integer.valueOf(shopConfigMapper.getConfig("ORDER_AUTO_FINISH_TIME")) * 24 * 3600 * 1000));
        orderMapper.updateByPrimaryKeySelective(order);
        //插入订单历史记录
        OrderHistory orderHistory = new OrderHistory();
        orderHistory.setCreateTime(new Date());
        orderHistory.setOrderId(order.getOrderId());
        orderHistory.setOpName(SessionUtils.getUserName());
        String expressName = expressMapper.findByExpressCode(order.getExpressCode());
        order.setExpressName(expressName);
        if (StringUtils.isNotBlank(expressName)) {
            orderHistory.setContent("由" + expressName + "开始发货，物流单号" + order.getExpressNum());
        } else {
            orderHistory.setContent("商家已经开始发货");
        }
        orderHistoryMapper.insertSelective(orderHistory);

        //将订单子表状态改为已发货
        String deliveryGoods = "";
        List<OrderItem> list = orderItemMapper.getListByOrderId(order.getOrderId());
        for (OrderItem orderItem : list) {
            orderItem.setStatus(EnumUtil.ORDER_ITEM_STATUS.已发货.getValue().byteValue());
            orderItemMapper.updateByPrimaryKeySelective(orderItem);
            deliveryGoods = orderItem.getGoodsName();
        }
        if (list.size() > 1) {
            deliveryGoods += "等" + list.size() + "件商品";
        }
        //发送微信消息
        Member member = memberMapper.selectByPrimaryKey(order.getMemberId());
        messageService.orderDeliveryMsg(order, deliveryGoods, member.getOpenId());
    }

    /**
     * 补零
     *
     * @param str
     * @param strLength
     * @return
     */
    private String addZeroForNum(String str, int strLength) {
        int strLen = str.length();
        StringBuffer sb;
        while (strLen < strLength) {
            sb = new StringBuffer();
            // 左(前)补0
            sb.append("0").append(str);
            str = sb.toString();
            strLen = str.length();
        }
        return str;
    }

    /**
     * 查询订单赠品列表
     *
     * @param orderId
     * @return
     */
    @Override
    public List<String> getOrderGiftList(Integer orderId) {
        return orderGiftMapper.getGiftList(orderId);
    }

    /**
     * 获取可以自动确认收货的订单
     *
     * @return
     */
    @Override
    public List<Order> getCanReceiptOrder() {
        return orderMapper.getCanReceiptOrder();
    }

    /**
     * 获取某些状态下的订单数量
     *
     * @param status
     * @return
     */
    @Override
    public Integer getOrderCountByStatus(byte status) {
        return orderMapper.getOrderCountByStatus(status);
    }

    /**
     * 从某一天起到现在的交易订单数量
     *
     * @param day
     * @return
     */
    @Override
    public Integer getTradeOrderByFromDay(String day) {
        return orderMapper.getTradeOrderByFromDay(day);
    }

    /**
     * 从某一天起到现在的交易金额
     *
     * @param day
     * @return
     */
    @Override
    public BigDecimal getTradeAmountByFromDay(String day) {
        return orderMapper.getTradeAmountByFromDay(day);
    }

    /**
     * 某一天的交易订单数量
     *
     * @param day
     * @return
     */
    @Override
    public Integer getTradeOrderByThatDay(String day) {
        return orderMapper.getTradeOrderByThatDay(day);
    }

    /**
     * 获取会员订单对应状态的总数量
     *
     * @param memberId
     * @param status
     * @return
     */
    @Override
    public int getCountByMemberId(Integer memberId, Byte status) {
        return orderMapper.getCountByMemberId(memberId, status);
    }
}
